<template>
  <div class="btnBox">
    <van-popup :close-on-click-overlay="false" v-model="show.isShow">
      <van-nav-bar :border="false">
        <template #title>
          <div class="title">在线报名</div>
        </template>
        <template #left>
          <van-icon color="#666" name="revoke" size="18" @click="closePopue" />
        </template>
      </van-nav-bar>

      <!-- 动态表单：循环渲染表单项 -->
      <van-form @submit="onSubmit" class="form-container">
        <!-- 1. 动态渲染所有输入类表单项（默认+自定义） -->
        <van-field
          v-for="(item, idx) in inputFormItems"
          :key="`input-${idx}-${item.name}`"
          v-if="item.visible"
          v-model="signUpForm[item.name]"
          :name="item.name"
          :label="item.label"
          :placeholder="`请输入${item.label}`"
          :type="item.type === 'textarea' ? 'textarea' : 'text'"
          :rows="item.rows || 1"
          :autosize="item.type === 'textarea' ? { minRows: 2 } : false"
          :rules="getFieldRules(item)"
          style="margin-bottom: 8px"
        />
        <!--   :rules="
            item.required
              ? [{ required: true, message: `请填写${item.label}` }]
              : []
          " -->

        <!-- 2. 单独渲染图片上传项（非van-field类型） -->
        <div v-if="imageFormItem.visible" class="image-upload-section">
          <div class="upload-tip" style="margin: 0 20px 16px">
            {{ imageFormItem.tip || "上传选手图片" }}
          </div>
          <van-uploader
            :max-count="imageFormItem.maxCount || 3"
            multiple
            v-model="fileList"
            :before-read="beforeRead"
            :after-read="afterRead"
            style="margin: 0 20px 16px"
            accept="image/*,image/heic,image/HEIC"
            @oversize="onOversize"
            @delete="onDelete"
          />
        </div>

        <!-- 表单提示文本 -->
        <div
          class="form-tip"
          style="margin: 15px 20px 16px; text-align: center"
        >
          以上信息仅作为活动主办方和您联系使用
        </div>

        <!-- 提交按钮 -->
        <div style="margin: 0 16px 16px">
          <van-button
            round
            block
            type="primary"
            native-type="submit"
            :style="show.buttonStyle"
          >
            提交报名
          </van-button>
        </div>
      </van-form>
    </van-popup>
  </div>
</template>

<script>
import heic2any from "heic2any";
import wx from "weixin-js-sdk";
import { Toast } from "vant";
import {
  dataUpdata,
  deletePhoto,
  submitSpeech,
  apiUploadImage,
  addPlayer,
} from "@/api/index.js";
import { mapActions, mapGetters, mapMutations } from "vuex";
export default {
  props: ["childrenData"],
  data() {
    return {
      show: { isShow: false, buttonStyle: "", type: 0 },
      userLocation: null,
      signUpForm: {}, // 动态表单数据（避免固定属性，适配自定义字段）
      fileList: [], // 图片上传列表
      PhotoLoading: false,
      // 存储解析后的活动配置（避免重复解析）
      receivedActivityInfo: {},
      openId: localStorage.getItem("openId"), //uuid
      vote_activityId: localStorage.getItem("vote_activityId"), //uuid
      isImageUploading: false, // 新增：标记图片是否正在上传中
    };
  },

  computed: {
    //  关键：从 Vuex 获取上传的图片列表（含唯一 ID）
    ...mapGetters(["getUploadedImages"]),
    // 1. 解析 registrationOptions（JSON字符串→对象）
    parsedRegistrationOptions() {
      if (!this.receivedActivityInfo.registrationOptions) return {};
      try {
        return JSON.parse(this.receivedActivityInfo.registrationOptions);
      } catch (err) {
        console.error("解析registrationOptions失败:", err);
        return {};
      }
    },

    // 2. 解析 customOptions（JSON字符串→数组）
    parsedCustomOptions() {
      if (!this.receivedActivityInfo.customOptions) return [];
      try {
        return JSON.parse(this.receivedActivityInfo.customOptions);
      } catch (err) {
        console.error("解析customOptions失败:", err);
        return [];
      }
    },

    // 1. 图片上传配置（完全依赖后端，无默认提示）
    imageFormItem() {
      const regOpt = this.parsedRegistrationOptions;
      // 仅当后端返回 imageName 且 imageRequired 不为隐藏时，才渲染图片上传
      const shouldShow =
        !!regOpt.imageName && regOpt.imageRequired !== "imgstime";
      return {
        visible: shouldShow,
        required: shouldShow ? regOpt.imageRequired === "imgsd" : false,
        tip: shouldShow ? `上传${regOpt.imageName}1-3` : "", // 无默认，后端imageName直接作为提示
        maxCount: 3,
      };
    },

    // 2. 输入类表单项（完全从后端提取，无任何默认字段）
    inputFormItems() {
      const regOpt = this.parsedRegistrationOptions;
      const customItems = this.parsedCustomOptions;
      const backendInputConfigs = [
        // 字段1：pName（关键修改：强制必填）
        {
          formKey: "name",
          labelKey: "pName",
          requiredKey: "pRequired", // 原错误："nameRequired"，修正为"pRequired" // 保留后端键名，但不再依赖其值判断必填
          type: "text",
        },
        // 字段2：手机号（不变，仍依赖后端配置）
        {
          formKey: "phone",
          labelKey: "phoneName",
          requiredKey: "phoneRequired",
          type: "text",
        },
        // 字段3：描述（不变，仍依赖后端配置）
        {
          formKey: "description",
          labelKey: "descriptionName",
          requiredKey: "descriptionRequired",
          type: "textarea",
          rows: 2,
        },
      ];

      // 从后端配置生成输入字段（仅修改name的required逻辑）
      const backendItems = backendInputConfigs.reduce((acc, config) => {
        const { formKey, labelKey, requiredKey, type, rows = 1 } = config;
        // 修正显示条件：pName 只需 labelKey 存在即可，其他字段仍需 requiredKey
        const isPName = formKey === "name";
        const showCondition = isPName
          ? regOpt[labelKey] // pName：只要有“演员名称”就显示
          : regOpt[labelKey] &&
            regOpt[requiredKey] &&
            regOpt[requiredKey] !== "imgstime"; // 其他字段原条件

        if (showCondition) {
          acc.push({
            name: formKey,
            label: regOpt[labelKey],
            type,
            rows,
            visible: true,
            required: isPName ? true : regOpt[requiredKey] === "imgsd", // pName 强制必填
          });
        }
        return acc;
      }, []);
      return [...backendItems];
    },
  },

  watch: {
    // 3. 监听 Vuex 图片状态变化，实时同步组件预览列表
    getUploadedImages(newVal) {
      if (Array.isArray(newVal)) {
        this.fileList = newVal.map((img) => ({
          url: img.url, // 图片预览地址（后端返回）
          id: img.id, // 图片唯一 ID（关键：用于删除定位）
          file: null, // 已上传图片无需保存 File 对象
        }));
        console.log("【组件预览列表同步】", this.fileList);
      }
    },
    // 监听活动数据变化，同步并初始化表单
    childrenData: {
      deep: true,
      handler(newVal) {
        if (newVal) {
          this.show.isShow = newVal.show;
          this.show.buttonStyle = newVal.buttonStyle;
          // 同步活动数据，触发计算属性更新
          this.receivedActivityInfo = newVal.activeInfo || {};
          // 初始化表单（清空旧数据）
          this.signUpForm = {};
          this.fileList = [];
          console.log("【动态表单】活动配置更新，表单已重置");
        }
      },
    },
  },
  created() {
    // 2. 组件创建时：从本地存储初始化 Vuex 图片状态，同步到预览列表
    // this.INIT_UPLOADED_IMAGES();
  },
  methods: {
    // 新增：根据字段类型生成验证规则（支持扩展其他字段）
    getFieldRules(item) {
      const rules = [];
      // 1. 通用必填规则（所有必填字段共用）
      if (item.required) {
        rules.push({
          required: true,
          message: `请填写${item.label}`,
          trigger: "submit", // 提交时触发（也可加 'blur' 失去焦点触发）
        });
      }
      // 2. 手机号专属格式规则（仅对 phone 字段生效）
      if (item.name === "phone") {
        rules.push({
          pattern: /^1[3-9]\d{9}$/,
          message: "请输入正确的手机号（11位数字）",
          trigger: ["blur", "submit"], // 失去焦点 + 提交时均触发验证
        });
      }
      return rules;
    },

    ...mapActions(["uploadImage", "deleteImage"]), // Vuex 的 uploadImage Action
    ...mapMutations(["INIT_UPLOADED_IMAGES", "CLEAR_UPLOADED_IMAGES"]),
    // 1. 表单验证（确保必填字段已填写，非必填不验证）
    validateSubmit() {
      const errors = [];
      const formData = this.signUpForm;

      // 仅验证必填字段
      this.inputFormItems.forEach((item) => {
        if (item.visible && item.required) {
          // 只校验「可见且必填」的字段
          const value = formData[item.name]?.trim() || "";
          if (!value) errors.push(`请填写${item.label}`);
        }
      });

      // 2. 修复：图片必填验证（错误加入 errors 数组，统一管理）
      if (this.imageFormItem.visible && this.imageFormItem.required) {
        // 图片未上传（fileList 为空）
        if (this.fileList.length === 0) {
          // 关键：将图片错误加入 errors 数组，而非单独弹 Toast
          errors.push("请上传选手图片");
        }
      }

      // 3. 统一错误提示 + 阻止提交（原有逻辑保留，但现在包含图片错误）
      console.log("🚀 ~ validateSubmit ~ errors:", errors);
      if (errors.length > 0) {
        // Toast.fail("请上传选手图片");
        console.log("🚀 ~ validateSubmit ~ errors:", errors);
        Toast.fail(errors.join("，")); // 所有错误合并为一个提示（如：“请填写选手名称，请上传选手图片”）
        // Toast.fail(errors); // 所有错误合并为一个提示（如：“请填写选手名称，请上传选手图片”）
        return false; // 验证不通过，阻止表单提交
      }

      return true;
    },
    // 2. 表单提交（包含必填字段+有值的非必填字段）
    async onSubmit() {
      try {
        // 新增：1. 先判断图片是否正在上传（必填时拦截）
        if (this.imageFormItem.visible && this.imageFormItem.required) {
          if (this.isImageUploading) {
            Toast.fail("图片上传中，请稍候再提交");
            return; // 阻止继续提交
          }
          // 2. 再判断图片是否已上传（原有验证逻辑已处理，但此处可加强提示）
          if (this.fileList.length === 0) {
            Toast.fail("请上传选手图片");
            return;
          }
        }

        if (!this.validateSubmit()) return;

        // 核心：创建空 JSON 对象（替代 FormData）
        const submitData = {};

        // 1. 处理表单可见字段（含必填/非必填，有值才传参）
        this.inputFormItems.forEach((item) => {
          if (item.visible) {
            // 仅处理「可见」的字段
            const rawValue = this.signUpForm[item.name];
            // 统一转为字符串并去空格（保持与原 FormData 数据格式一致）
            const fieldValue = (rawValue?.toString() || "").trim();

            // 有值则添加到 JSON 对象（非必填未填写则忽略，必填已通过验证）
            if (fieldValue) {
              submitData[item.name] = fieldValue; // JSON 属性赋值（替代 formData.append）
              console.log(
                `【${item.required ? "必填" : "非必填"}字段】${item.label}:`,
                fieldValue
              );
            } else if (!item.required) {
              console.log(
                `【非必填字段未填写】${item.label}（${item.name}）忽略`
              );
            }
          }
        });

        // 2. 处理固定字段（openId、活动ID，有值才传参）
        if (this.openId?.trim()) {
          submitData.openId = this.openId.trim(); // 直接赋值到 JSON 对象
        }
        if (this.vote_activityId?.trim()) {
          submitData.activityId = this.vote_activityId.trim();
        }

        // 3. 处理图片字段（可见且有上传才传参，JSON 中用数组存储多图）
        if (this.imageFormItem.visible) {
          // 提取有效图片 URL（去空格+过滤空值）
          const imageUrls = this.getUploadedImages
            .map((img) => img.url?.trim() || "")
            .filter((url) => url);

          // 有图片才添加到 JSON 对象（数组格式，替代多次 append "imageUrls"）
          if (imageUrls.length > 0) {
            submitData.imageUrl = imageUrls;
          }
        }

        // 4. 打印最终提交的 JSON 参数（替代 FormData 遍历）
        console.log("=== 最终提交的 JSON 参数 ===");
        Object.entries(submitData).forEach(([key, value]) => {
          console.log(`${key}: ${value}`);
        });

        // 5. 提交接口（传 JSON 对象，而非 FormData）
        this.$toast.loading({ message: "提交中...", forbidClick: true });
        // 注意：若接口要求 Content-Type: application/json，axios 会自动处理（传对象时默认设置）
        const response = await addPlayer(submitData);

        if (response.data?.code === 0) {
          this.$toast.success("报名成功！");
          this.show.isShow = false;
          this.signUpForm = {};
          this.fileList = [];
          this.CLEAR_UPLOADED_IMAGES();
          this.$emit("child-event", this.show);
        } else {
          this.CLEAR_UPLOADED_IMAGES();
          this.$toast.fail(response.data?.msg || "报名失败，请重试");
        }
      } catch (error) {
        console.error("报名接口调用失败:", error);
        this.$toast.fail("网络异常，报名失败");
      } finally {
        // this.$toast.clear(); // 修复原代码中 finally 未清除 toast 的问题
      }
    },

    // 3. 图片处理：HEIC转JPG（原有逻辑保留）
    async convertHEIC(file) {
      try {
        if (file.type.match(/heic/gi)) {
          const convertedBlob = await heic2any({
            blob: file,
            toType: "image/jpeg",
            quality: 0.8,
          });
          return new File(
            [convertedBlob],
            file.name.replace(/\.[^/.]+$/, ".jpg"),
            { type: "image/jpeg" }
          );
        }
        return file;
      } catch (error) {
        console.error("HEIC转换失败:", error);
        return file;
      }
    },

    // 4. 图片上传前校验（原有逻辑保留）
    beforeRead(file) {
      const MAX_SIZE = 30 * 1024 * 1024; // 修正为30MB（原99MB过大）
      const validTypes = [
        "image/jpeg",
        "image/png",
        "image/heic",
        "image/HEIC",
        "image/jpg",
      ];
      const files = Array.isArray(file) ? file : [file];

      for (const f of files) {
        if (!validTypes.includes(f.type)) {
          Toast("仅支持JPG/PNG/HEIC格式图片");
          return false;
        }
        if (f.size > MAX_SIZE) {
          Toast("单个文件大小不能超过30MB");
          return false;
        }
      }
      return true;
    },

    // 5. 图片上传后处理（原有逻辑保留）
    async afterRead(file) {
      const files = Array.isArray(file) ? file : [file];
      if (files.length === 0) return;
      try {
        this.isImageUploading = true; // 开始上传：标记为“上传中”
        this.PhotoLoading = true;
        let successCount = 0;

        // 循环处理每张图片（确保所有图片都上传完成）
        for (const f of files) {
          const convertedFile = await this.convertHEIC(f.file);
          if (!convertedFile) {
            console.warn("跳过无效文件:", f);
            continue;
          }

          const formData = new FormData();
          formData.append("file", convertedFile);
          formData.append("activityId", this.receivedActivityInfo?.id || "");

          // 等待当前图片上传成功（关键：await 确保顺序执行）
          await this.uploadImage(formData);
          successCount++;
        }

        // 上传完成：提示成功数量
        Toast.success(`成功上传 ${successCount}/${files.length} 张图片`);
      } catch (error) {
        console.error("图片上传流程失败:", error);
        Toast.fail("图片上传失败，请重新上传");
      } finally {
        this.isImageUploading = false; // 无论成功/失败，都标记为“上传完成”
        this.PhotoLoading = false;
      }
    },

    // 6. 其他原有方法（保留）
    onOversize() {
      Toast("图片大小不能超过30MB");
    },
    async onDelete(file) {
      // 防错：确保要删除的图片有唯一 ID
      if (!file?.id) {
        console.warn("跳过无 ID 的图片删除");
        return;
      }

      try {
        // 调用 Vuex 的 deleteImage Action（传递图片 ID）
        await this.deleteImage(file.id);
        // 删除成功提示
        Toast.success("图片已删除");
      } catch (error) {
        // 捕获删除失败（如网络错误、Vuex 异常）
        console.error("图片删除失败:", error);
        Toast.fail("删除失败，请重试");
      }
    },
    closePopue() {
      this.show.isShow = false;
      this.$emit("child-event", this.show);
      this.userLocation = null;
      this.CLEAR_UPLOADED_IMAGES();
    },
  },
};
</script>

<style scoped>
.van-popup {
  width: 100%;
  height: 100%;
  overflow-y: auto;
}
.title {
  color: #666;
}
.form-container {
  padding: 16px 0;
}
.image-upload-section {
  margin-bottom: 8px;
}
.form-tip {
  color: #888;
  font-size: 14px;
}

/* 图片上传样式优化 */
::v-deep .van-uploader__wrapper {
  width: 100%;
}
::v-deep .van-uploader__upload,
::v-deep .van-uploader__file {
  width: 100px;
  height: 100px;
  margin: 0 6px 6px 0;
}
.van-popup {
  width: 100%;
  height: 100%;
}

.title {
  color: #666;
}

.icon {
  color: #666;
  font-size: 18px;
}

::v-deep .van-image {
  display: block;
  width: 100px;
  height: 100px;
  overflow: hidden;
}

::v-deep .van-uploader__wrapper {
  width: 100%;
}

::v-deep .van-uploader__upload {
  width: 100px;
  height: 100px;
}

::v-deep .van-uploader__preview,
.van-uploader__upload {
  margin: 0 6px 6px 0;
}

::v-deep .van-cell--clickable {
  margin-top: 25px;
  border: 1px solid #eceaea;
}

.location {
  color: #666;
  font-size: 16px;
  margin: 10px 0px 0px 20px;
}

.dateClass {
  border-bottom: 1px solid #f4f4f4;
}

::v-deep .van-cell__value {
  text-align: left;
}

::v-deep .van-cell__title,
.van-cell__value {
  -webkit-box-flex: 1;
  /* -webkit-flex: 1; */
  /* flex: 1; */
}

::v-deep .van-uploader__file {
  width: 100px;
  height: 100px;
}

.locationBer {
  width: 70%;
}

.dataBer {
  height: 32px;
  line-height: 32px;
  margin-right: 18px;
}

::v-deep .van-cell {
  color: #323233 !important;
  background-color: #fff !important;
}

.wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
}

.block {
  width: 120px;
  height: 120px;
  background-color: #fff;
}
::v-deep .van-toast {
  z-index: 99999 !important; /* 强制覆盖默认层级 */
}

::v-deep .van-nav-bar__content {
  margin-top: 20px;
}
</style>
